home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / TIFF / TEXTIFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  5.6 KB  |  207 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1997. */
  3.  
  4. /* This program is freely distributable without licensing fees  and is
  5.    provided without guarantee or warrantee expressed or  implied. This
  6.    program is -not- in the public domain. */
  7.  
  8. /* X compile line: cc -o textiff textiff.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
  9.  
  10. /* textiff is a simple TIFF file viewer using Sam Leffler's libtiff, GLUT,
  11.    and OpenGL.  Unlike the showtiff example that simply uses glDrawPixels to
  12.    draw the image, textiff loads the texture into texture memory and then
  13.    renders the image as a textured polygon.  This enables fast hardware
  14.    accelerated image rotates.  Use the left and right arrow keys to rotate
  15.    the texture arround. */
  16.  
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <GL/glut.h>
  21. #include <tiffio.h>     /* Sam Leffler's libtiff library. */
  22.  
  23. TIFFRGBAImage img;
  24. uint32 *raster;
  25. uint32 *texture;
  26. tsize_t npixels;
  27. int tw, th;
  28. int angle;
  29.  
  30. int hasABGR = 0;
  31. int doubleBuffer = 1;
  32. char *filename = NULL;
  33.  
  34. void
  35. display(void)
  36. {
  37.   glClear(GL_COLOR_BUFFER_BIT);
  38.   glPushMatrix();
  39.  
  40.   /* Rotate by angle. */
  41.   glRotatef(angle, 0, 0, 1);
  42.  
  43.   /* Draw a rectangle onto which the TIFF image will get textured.  Notice
  44.      that the texture coordinates are set to each corner of the texture
  45.      image. */
  46.   glBegin(GL_QUADS);
  47.   glTexCoord2i(0, 0);
  48.   glVertex2i(-1, -1);
  49.   glTexCoord2i(1, 0);
  50.   glVertex2i(1, -1);
  51.   glTexCoord2i(1, 1);
  52.   glVertex2i(1, 1);
  53.   glTexCoord2i(0, 1);
  54.   glVertex2i(-1, 1);
  55.   glEnd();
  56.  
  57.   glPopMatrix();
  58.   if (doubleBuffer) {
  59.     glutSwapBuffers();
  60.   }
  61. }
  62.  
  63. /* If the left or right arrows are pressed, rotate five degrees either
  64.    direction and request a redraw of the window. */
  65. /* ARGSUSED1 */
  66. void
  67. special(int key, int x, int y)
  68. {
  69.   switch (key) {
  70.   case GLUT_KEY_LEFT:
  71.     angle -= 5;
  72.     angle %= 360;
  73.     glutPostRedisplay();
  74.     break;
  75.   case GLUT_KEY_RIGHT:
  76.     angle += 5;
  77.     angle %= 360;
  78.     glutPostRedisplay();
  79.     break;
  80.   }
  81. }
  82.  
  83. int
  84. main(int argc, char **argv)
  85. {
  86.   TIFF *tif;
  87.   char emsg[1024];
  88.   int i;
  89.  
  90.   glutInit(&argc, argv);
  91.   for (i = 1; i < argc; i++) {
  92.     if (!strcmp(argv[i], "-sb")) {
  93.       doubleBuffer = 0;
  94.     } else {
  95.       filename = argv[i];
  96.     }
  97.   }
  98.   if (filename == NULL) {
  99.     fprintf(stderr, "usage: textiff [GLUT-options] [-sb] TIFF-file\n");
  100.     exit(1);
  101.   }
  102.   tif = TIFFOpen(filename, "r");
  103.   if (tif == NULL) {
  104.     fprintf(stderr, "Problem showing %s\n", filename);
  105.     exit(1);
  106.   }
  107.   if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
  108.     npixels = (tsize_t) (img.width * img.height);
  109.     raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
  110.     if (raster != NULL) {
  111.       if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
  112.         TIFFError(filename, emsg);
  113.         exit(1);
  114.       }
  115.     }
  116.     TIFFRGBAImageEnd(&img);
  117.   } else {
  118.     TIFFError(filename, emsg);
  119.     exit(1);
  120.   }
  121.   if (doubleBuffer) {
  122.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  123.   } else {
  124.     glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  125.   }
  126.   glutInitWindowSize((int) img.width, (int) img.height);
  127.   glutCreateWindow("textiff");
  128.   glutDisplayFunc(display);
  129.   glutSpecialFunc(special);
  130. #ifdef GL_EXT_abgr
  131.   if (glutExtensionSupported("GL_EXT_abgr"))
  132.     hasABGR = 1;
  133. #else
  134.   hasABGR = 0;
  135. #endif
  136.   /* If cannot directly display ABGR format, we need to reverse the component
  137.      ordering in each pixel. :-( */
  138.   if (!hasABGR) {
  139.     int i;
  140.  
  141.     for (i = 0; i < npixels; i++) {
  142.       register unsigned char *cp = (unsigned char *) &raster[i];
  143.       int t;
  144.  
  145.       t = cp[3];
  146.       cp[3] = cp[0];
  147.       cp[0] = t;
  148.       t = cp[2];
  149.       cp[2] = cp[1];
  150.       cp[1] = t;
  151.     }
  152.   }
  153.   /* OpenGL's default unpack (and pack) alignment is 4.  In the case of the
  154.      data returned by libtiff which is already aligned on 32-bit boundaries,
  155.      setting the pack to 1 isn't strictly necessary. */
  156.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  157.   gluOrtho2D(-1, 1, -1, 1);
  158.  
  159.   /* Linear sampling within a mipmap level. */
  160.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  161.     GL_LINEAR_MIPMAP_NEAREST);
  162.  
  163.   glEnable(GL_TEXTURE_2D);
  164.  
  165.   /* A TIFF file could be any size; OpenGL textures are allowed to have a
  166.      width and height that is a power of two (32, 64, 128, etc.). To maximize
  167.      the use of available texture memory, we scale the image to gluScaleImage
  168.      to the next larger power of 2 width or height dimension (not exceeding
  169.      512, don't want to use too much texture memory!).  This rescaling can
  170.      result in a bit of image bluring because of the resampling done by
  171.      gluScaleImage.  An alternative would be to change the texture coordinates 
  172.      to only use a portion texture area. */
  173.  
  174.   tw = 1 << (int) ceil(log(img.width) / log(2.0));
  175.   th = 1 << (int) ceil(log(img.height) / log(2.0));
  176.   if (tw > 512)
  177.     tw = 512;
  178.   if (th > 512)
  179.     th = 512;
  180.   texture = (uint32 *) malloc(sizeof(GLubyte) * 4 * tw * th);
  181.  
  182. #ifdef GL_EXT_abgr
  183. #define APPROPRIATE_FORMAT (hasABGR ? GL_ABGR_EXT : GL_RGBA)
  184. #else
  185. #define APPROPRIATE_FORMAT GL_RGBA
  186. #endif
  187.  
  188.   gluScaleImage(APPROPRIATE_FORMAT,
  189.     (GLsizei) img.width, (GLsizei) img.height, GL_UNSIGNED_BYTE, raster,
  190.     tw, th, GL_UNSIGNED_BYTE, texture);
  191.   _TIFFfree(raster);
  192.  
  193.   /* Build mipmaps for the texture image.  Since we are not scaling the image
  194.      (we easily could by calling glScalef), creating mipmaps is not really
  195.      useful, but it is done just to show how easily creating mipmaps is. */
  196.   gluBuild2DMipmaps(GL_TEXTURE_2D, 4, tw, th,
  197.     APPROPRIATE_FORMAT, GL_UNSIGNED_BYTE,
  198.     texture);
  199.  
  200.   /* Use a gray background so TIFF images with black backgrounds will
  201.      show against textiff's background. */
  202.   glClearColor(0.2, 0.2, 0.2, 1.0);
  203.  
  204.   glutMainLoop();
  205.   return 0;             /* ANSI C requires main to return int. */
  206. }
  207.